import re
from models import *
import time

"""
class Timer:
    def __init__(self, start=True):
        if start:
            self.start_time = time.time()
            self.acc = 0    # 累计的时间
        else:
            self.start_time = None
            self.acc = 0

    def pause(self):
        assert(self.start_time is not None)
        now = time.time()
        self.acc += now - self.start_time

    def resume(self):
        self.start_time = time.time()

    def elapsed(self):
        assert(self.start_time is not None)
        now = time.time()
        return now - self.start_time + self.acc
"""

def set_up_log(debug=True):
    if debug:
        l.basicConfig(level=l.INFO,format='%(filename)s@%(funcName)s#%(lineno)d: %(message)s')
    else:
        l.basicConfig(level=l.CRITICAL)

class Output:
    """用于输出最终答案的类
    输出的数据可以分为如下几类:
    1. 购买服务器
    2. 迁移服务器
    3. 对于创建请求的响应
    """

    def __init__(self, file=sys.stdout):
        self.records = []
        self.purchase_list = []
        self.migrate_list = []
        self.response_list = []
        self.file = file

    def output(self):
        """输出最终结果到file中"""
        for i in range(len(self.records)):
            purchase, migrate, resp = self.records[i]
            self._output_one_day(purchase, migrate, resp, self.file, i == len(self.records)-1)
        self.file.flush()
        # self._output_one_day(self.purchase_dict, self.migrate_list, self.response_list)

    def output_today(self):
        self._output_one_day(self.purchase_list, self.migrate_list, self.response_list, self.file)

    def _output_one_day(self, purchase: list, migrate: list, resp: list, file=sys.stdout, last=False):
        """输出一天的操作
        按照文档，需要顺序输出：
        1. (purchase, <购买的服务器类型>)
        2. (<服务器类型>, <购买的数量>)
        3. (migration, <迁移的次数>)
        4. (<迁移列表>)
        5. (<服务器id>) 或者 (<服务器id>, A|B) #这是对add请求的响应
        :param file:
        :return:
        """
        # 购买
        file.write('(purchase, %d)\n' % (len(purchase)))
        for name, amount in purchase:
            file.write('(%s, %d)\n' % (name, amount))

        # 迁移
        file.write('(migration, %d)\n' % (len(migrate)))
        for m in migrate:
            file.write(m + '\n')

        # 对add的响应
        if last:
            file.write('\n'.join(resp))
        else:
            for r in resp:
                file.write(r + '\n')

    def start_a_new_day(self):
        """
        输出每天统计并存储，最后一并输出
        这个方法用于另开一个存储空间，用于存储第二天的数据
        """
        self.records.append((self.purchase_list, self.migrate_list, self.response_list))
        self.purchase_list = []
        self.migrate_list = []
        self.response_list = []

    def purchase_server(self, type: Servertype, amount=1):
        """购买物理机"""
        self.purchase_list.append((type.name, amount))

    def migrate(self, vm_id: str, server_id: int):
        """迁移到双结点"""
        self.migrate_list.append('(%s, %d)' % (vm_id, server_id))

    def migrate_single_node(self, vm_id: str, server_id: int, a_or_b: str):
        """迁移到单结点"""
        self.migrate_list.append('(%s, %d, %s)' % (vm_id, server_id, a_or_b.upper()))

    def allocate(self, server_id):
        """分配虚拟机到物理服务器"""
        self.response_list.append('({})'.format(server_id))

    def allocate_single_node(self, server_id: int, a_or_b: str):
        """分配虚拟机到物理服务器的单核"""
        self.response_list.append('(%d, %s)' % (server_id, a_or_b.upper()))


class Parser:
    def __init__(self):
        pass

    @staticmethod
    def parse_server(s: str):
        """解析server类型"""
        parsed = re.sub(r'[() ]', '', s.strip()).split(',')
        return Servertype(parsed[0], *[int(_) for _ in parsed[1:]])

    @staticmethod
    def parse_vm(s: str):
        """解析vm类型"""
        parsed = re.sub(r'[() ]', '', s.strip()).split(',')
        return Vmtype(parsed[0], *[int(_) for _ in parsed[1:]])

    @staticmethod
    def parse_operation(s: str):
        """解析操作类型"""
        parsed = re.sub(r'[() ]', '', s.strip()).split(',')
        if parsed[0] == 'add':
            return Operation(Operation.Op.ADD, parsed[2], parsed[1])
        elif parsed[0] == 'del':  # del
            return Operation(Operation.Op.DEL, parsed[1])
        else:
            l.fatal('fatal parsing error')
            sys.exit(-1)


def read_data_z_edition(file=sys.stdin) -> Tuple[List[List[Operation]], List[Servertype], Dict[str, Vmtype]]:
    parser = Parser()
    op_list:List[List[Operation]] = []
    server_type_list:List[Servertype] = []
    vm_type_dict:Dict[str,Vmtype] = dict()

    # 物理机类型数量
    type_num = int(file.readline())

    # 读取物理机类型
    for i in range(type_num):
        server_type = parser.parse_server(file.readline())
        server_type_list.append(server_type)

    # 虚拟机类型数量
    vm_num = int(file.readline())

    # 读取虚拟机类型
    for i in range(vm_num):
        vm_type = parser.parse_vm(file.readline())
        vm_type_dict[vm_type.name] = vm_type

    # 天数
    days = int(file.readline())
    for day_i in range(days):
        # 操作数
        op_num = int(file.readline())
        ops_day = []
        for _ in range(op_num):
            s = file.readline()
            op = parser.parse_operation(s)
            ops_day.append(op)
        op_list.append(ops_day)
    return op_list, server_type_list, vm_type_dict